
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title>kubernetes资源对象之security context</title>
            </head>
            <body>
            <a href="https://andyoung.blog.csdn.net">原作者博客</a>
            <div id="content_views" class="markdown_views prism-atom-one-light">
                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                    </svg>
                    <p>安全上下文（Security Context）定义 Pod 或 Container 的的权限和访问控制。 安全上下文包括但不限于：</p> 
<ul><li> <p>自主访问控制（Discretionary Access Control）：基于 用户 ID（UID）和组 ID（GID）. 来判定对对象（例如文件）的访问权限。</p> </li><li> <p>安全性增强的 Linux（SELinux： 为对象赋予安全性标签。</p> </li><li> <p>以特权模式或者非特权模式运行。</p> </li><li> <p>Linux 权能: 为进程赋予 root 用户的部分特权而非全部特权。</p> </li><li> <p>AppArmor：使用程序框架来限制个别程序的权能。</p> </li><li> <p>Seccomp：过滤进程的系统调用。</p> </li><li> <p>AllowPrivilegeEscalation：控制进程是否可以获得超出其父进程的特权。 此布尔值直接控制是否为容器进程设置 <a href="https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt" rel="nofollow"><code>no_new_privs</code></a>标志。 当容器以特权模式运行或者具有 <code>CAP_SYS_ADMIN</code> 权能时，AllowPrivilegeEscalation 总是为 true。</p> </li><li> <p>readOnlyRootFilesystem：以只读方式加载容器的根文件系统。</p> </li></ul> 
<p>以上条目不是安全上下文设置的完整列表 – 请参阅 SecurityContext 了解其完整列表。</p> 
<h3><a id="_Pod__16"></a>为 Pod 设置安全性上下文</h3> 
<p>要为 Pod 设置安全性设置，可在 Pod 规约中包含 <code>securityContext</code> 字段。<code>securityContext</code> 字段值是一个 <a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core" rel="nofollow">PodSecurityContext</a> 对象。你为 Pod 所设置的安全性配置会应用到 Pod 中所有 Container 上。 下面是一个 Pod 的配置文件，该 Pod 定义了 <code>securityContext</code> 和一个 <code>emptyDir</code> 卷：</p> 
<pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> security<span class="token punctuation">-</span>context<span class="token punctuation">-</span>demo
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">securityContext</span><span class="token punctuation">:</span>
    <span class="token key atrule">runAsUser</span><span class="token punctuation">:</span> <span class="token number">1000</span>
    <span class="token key atrule">runAsGroup</span><span class="token punctuation">:</span> <span class="token number">3000</span>
    <span class="token key atrule">fsGroup</span><span class="token punctuation">:</span> <span class="token number">2000</span>
  <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> sec<span class="token punctuation">-</span>ctx<span class="token punctuation">-</span>vol
    <span class="token key atrule">emptyDir</span><span class="token punctuation">:</span> <span class="token punctuation">{<!-- --></span><span class="token punctuation">}</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> sec<span class="token punctuation">-</span>ctx<span class="token punctuation">-</span>demo
    <span class="token key atrule">image</span><span class="token punctuation">:</span> busybox
    <span class="token key atrule">command</span><span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token string">"sh"</span><span class="token punctuation">,</span> <span class="token string">"-c"</span><span class="token punctuation">,</span> <span class="token string">"sleep 1h"</span> <span class="token punctuation">]</span>
    <span class="token key atrule">volumeMounts</span><span class="token punctuation">:</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> sec<span class="token punctuation">-</span>ctx<span class="token punctuation">-</span>vol
      <span class="token key atrule">mountPath</span><span class="token punctuation">:</span> /data/demo
    <span class="token key atrule">securityContext</span><span class="token punctuation">:</span>
      <span class="token key atrule">allowPrivilegeEscalation</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>
</code></pre> 
<p>在配置文件中，<code>runAsUser</code> 字段指定 Pod 中的所有容器内的进程都使用用户 ID 1000 来运行。<code>runAsGroup</code> 字段指定所有容器中的进程都以主组 ID 3000 来运行。 如果忽略此字段，则容器的主组 ID 将是 root（0）。 当 <code>runAsGroup</code> 被设置时，所有创建的文件也会划归用户 1000 和组 3000。 由于 <code>fsGroup</code> 被设置，容器中所有进程也会是附组 ID 2000 的一部分。 卷 <code>/data/demo</code> 及在该卷中创建的任何文件的属主都会是组 ID 2000。</p> 
<p>创建该 Pod：</p> 
<pre><code class="prism language-shell">kubectl apply -f https://k8s.io/examples/pods/security/security-context.yaml
</code></pre> 
<p>检查 Pod 的容器处于运行状态：</p> 
<pre><code class="prism language-shell">kubectl get pod security-context-demo
</code></pre> 
<p>开启一个 Shell 进入到运行中的容器：</p> 
<pre><code class="prism language-shell">kubectl <span class="token builtin class-name">exec</span> -it security-context-demo -- <span class="token function">sh</span>
</code></pre> 
<p>在你的 Shell 中，列举运行中的进程：</p> 
<pre><code class="prism language-shell"><span class="token function">ps</span>
</code></pre> 
<p>输出显示进程以用户 1000 运行，即 <code>runAsUser</code> 所设置的值：</p> 
<pre><code class="prism language-shell">PID   <span class="token environment constant">USER</span>     TIME  COMMAND
    <span class="token number">1</span> <span class="token number">1000</span>      <span class="token number">0</span>:00 <span class="token function">sleep</span> 1h
    <span class="token number">6</span> <span class="token number">1000</span>      <span class="token number">0</span>:00 <span class="token function">sh</span>
<span class="token punctuation">..</span>.
</code></pre> 
<p>在你的 Shell 中，进入 <code>/data</code> 目录列举其内容：</p> 
<pre><code class="prism language-shell"><span class="token builtin class-name">cd</span> /data
<span class="token function">ls</span> -l
</code></pre> 
<p>输出显示 <code>/data/demo</code> 目录的组 ID 为 2000，即 <code>fsGroup</code> 的设置值：</p> 
<pre><code class="prism language-shell">drwxrwsrwx <span class="token number">2</span> root <span class="token number">2000</span> <span class="token number">4096</span> Jun  <span class="token number">6</span> <span class="token number">20</span>:08 demo
</code></pre> 
<p>在你的 Shell 中，进入到 <code>/data/demo</code> 目录下创建一个文件：</p> 
<pre><code class="prism language-shell"><span class="token builtin class-name">cd</span> demo
<span class="token builtin class-name">echo</span> hello <span class="token operator">&gt;</span> testfile
</code></pre> 
<p>列举 <code>/data/demo</code> 目录下的文件：</p> 
<pre><code class="prism language-shell"><span class="token function">ls</span> -l
</code></pre> 
<p>输出显示 <code>testfile</code> 的组 ID 为 2000，也就是 <code>fsGroup</code> 所设置的值：</p> 
<pre><code class="prism language-shell">-rw-r--r-- <span class="token number">1</span> <span class="token number">1000</span> <span class="token number">2000</span> <span class="token number">6</span> Jun  <span class="token number">6</span> <span class="token number">20</span>:08 testfile
</code></pre> 
<p>运行下面的命令：</p> 
<pre><code class="prism language-shell"><span class="token function">id</span>
</code></pre> 
<p>输出为：</p> 
<pre><code>uid=1000 gid=3000 groups=2000
</code></pre> 
<p>你会看到 <code>gid</code> 值为 3000，也就是 <code>runAsGroup</code> 字段的值。 如果 <code>runAsGroup</code> 被忽略，则 <code>gid</code> 会取值 0（root），而进程就能够与 root 用户组所拥有以及要求 root 用户组访问权限的文件交互。</p> 
<p>退出你的 Shell：</p> 
<pre><code class="prism language-shell"><span class="token builtin class-name">exit</span>
</code></pre> 
<h3><a id="_Pod__133"></a>为 Pod 配置卷访问权限和属主变更策略</h3> 
<p><strong>FEATURE STATE:</strong> <code>Kubernetes v1.20 [beta]</code></p> 
<p>默认情况下，Kubernetes 在挂载一个卷时，会递归地更改每个卷中的内容的属主和访问权限，使之与 Pod 的 <code>securityContext</code> 中指定的 <code>fsGroup</code> 匹配。 对于较大的数据卷，检查和变更属主与访问权限可能会花费很长时间，降低 Pod 启动速度。 你可以在 <code>securityContext</code> 中使用 <code>fsGroupChangePolicy</code> 字段来控制 Kubernetes 检查和管理卷属主和访问权限的方式。</p> 
<p><strong>fsGroupChangePolicy</strong> - <code>fsGroupChangePolicy</code> 定义在卷被暴露给 Pod 内部之前对其 内容的属主和访问许可进行变更的行为。此字段仅适用于那些支持使用 <code>fsGroup</code> 来 控制属主与访问权限的卷类型。此字段的取值可以是：</p> 
<ul><li><code>OnRootMismatch</code>：只有根目录的属主与访问权限与卷所期望的权限不一致时， 才改变其中内容的属主和访问权限。这一设置有助于缩短更改卷的属主与访问 权限所需要的时间。</li><li><code>Always</code>：在挂载卷时总是更改卷中内容的属主和访问权限。</li></ul> 
<p>例如：</p> 
<pre><code class="prism language-yaml"><span class="token key atrule">securityContext</span><span class="token punctuation">:</span>
  <span class="token key atrule">runAsUser</span><span class="token punctuation">:</span> <span class="token number">1000</span>
  <span class="token key atrule">runAsGroup</span><span class="token punctuation">:</span> <span class="token number">3000</span>
  <span class="token key atrule">fsGroup</span><span class="token punctuation">:</span> <span class="token number">2000</span>
  <span class="token key atrule">fsGroupChangePolicy</span><span class="token punctuation">:</span> <span class="token string">"OnRootMismatch"</span>
</code></pre> 
<p><strong>说明：</strong> 此字段对于<code>secret</code>、 <code>configMap</code>和 <code>emptydir</code> 这类临时性存储无效。</p> 
<h3><a id="_Container__158"></a>为 Container 设置安全性上下文</h3> 
<p>若要为 Container 设置安全性配置，可以在 Container 清单中包含 <code>securityContext</code> 字段。<code>securityContext</code> 字段的取值是一个 SecurityContext 对象。你为 Container 设置的安全性配置仅适用于该容器本身，并且所指定的设置 在与 Pod 层面设置的内容发生重叠时，会重载后者。Container 层面的设置不会影响 到 Pod 的卷。</p> 
<p>下面是一个 Pod 的配置文件，其中包含一个 Container。Pod 和 Container 都有 <code>securityContext</code> 字段：</p> 
<pre><code class="prism language-yaml"><span class="token key atrule">apiVersion</span><span class="token punctuation">:</span> v1
<span class="token key atrule">kind</span><span class="token punctuation">:</span> Pod
<span class="token key atrule">metadata</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> security<span class="token punctuation">-</span>context<span class="token punctuation">-</span>demo<span class="token punctuation">-</span><span class="token number">2</span>
<span class="token key atrule">spec</span><span class="token punctuation">:</span>
  <span class="token key atrule">securityContext</span><span class="token punctuation">:</span>
    <span class="token key atrule">runAsUser</span><span class="token punctuation">:</span> <span class="token number">1000</span>
  <span class="token key atrule">containers</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> sec<span class="token punctuation">-</span>ctx<span class="token punctuation">-</span>demo<span class="token punctuation">-</span><span class="token number">2</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> gcr.io/google<span class="token punctuation">-</span>samples/node<span class="token punctuation">-</span>hello<span class="token punctuation">:</span><span class="token number">1.0</span>
    <span class="token key atrule">securityContext</span><span class="token punctuation">:</span>
      <span class="token key atrule">runAsUser</span><span class="token punctuation">:</span> <span class="token number">2000</span>
      <span class="token key atrule">allowPrivilegeEscalation</span><span class="token punctuation">:</span> <span class="token boolean important">false</span>
</code></pre> 
<p>创建该 Pod：</p> 
<pre><code class="prism language-shell">kubectl apply -f https://k8s.io/examples/pods/security/security-context-2.yaml
</code></pre> 
<p>验证 Pod 中的容器处于运行状态：</p> 
<pre><code class="prism language-shell">kubectl get pod security-context-demo-2
</code></pre> 
<p>启动一个 Shell 进入到运行中的容器内：</p> 
<pre><code class="prism language-shell">kubectl <span class="token builtin class-name">exec</span> -it security-context-demo-2 -- <span class="token function">sh</span>
</code></pre> 
<p>在你的 Shell 中，列举运行中的进程：</p> 
<pre><code class="prism language-shell"><span class="token function">ps</span> aux
</code></pre> 
<p>输出显示进程以用户 2000 账号运行。该值是在 Container 的 <code>runAsUser</code> 中设置的。 该设置值重载了 Pod 层面所设置的值 1000。</p> 
<pre><code>USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
2000         1  0.0  0.0   4336   764 ?        Ss   20:36   0:00 /bin/sh -c node server.js
2000         8  0.1  0.5 772124 22604 ?        Sl   20:36   0:00 node server.js
...
</code></pre> 
<p>退出你的 Shell：</p> 
<pre><code class="prism language-shell"><span class="token builtin class-name">exit</span>
</code></pre>
                </div>
            </body>
            </html>
            